package aliyunpan

import (
	"center-platform/config"
	"center-platform/utils"
	"encoding/json"
	"fmt"
	"time"
)

type AliYunPan struct {
	ClientId     string
	ClientSecret string
}

var Host = "https://openapi.alipan.com"

type AuthQRCode struct {
	ClientId            string   `json:"client_id"`
	ClientSecret        string   `json:"client_secret"`
	Scopes              []string `json:"scopes"`
	CodeChallengeMethod string   `json:"code_challenge_method"`
}

type AccessTokenReq struct {
	ClientId     string `json:"client_id"`
	ClientSecret string `json:"client_secret"`
	GrantType    string `json:"grant_type"`
	Code         string `json:"code"`
	RefreshToken string `json:"refresh_token"`
	CodeVerifier string `json:"code_verifier"`
}

type AuthQrCodeResp struct {
	Code      string `json:"code"`
	Message   string `json:"message"`
	RequestId string `json:"requestId"`
	QrCodeUrl string `json:"qr_code_url"`
	Sid       string `json:"sid"`
}

type AuthQrcodeStatusResp struct {
	Code      string `json:"code"`
	Message   string `json:"message"`
	RequestId string `json:"requestId"`
	Status    string `json:"status"`
	AuthCode  string `json:"authCode"`
}

type AccessTokenResp struct {
	Code         string `json:"code"`
	Message      string `json:"message"`
	RequestId    string `json:"requestId"`
	TokenType    string `json:"token_type"`
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	ExpiresIn    int    `json:"expires_in"`
}

type DriverInfoResp struct {
	Code            string `json:"code"`
	Message         string `json:"message"`
	RequestId       string `json:"requestId"`
	UserId          string `json:"user_id"`
	Name            string `json:"name"`
	Avatar          string `json:"avatar"`
	DefaultDriveId  string `json:"default_drive_id"`
	ResourceDriveId string `json:"resource_drive_id"`
	BackUpDriveId   string `json:"back_up_drive_id"`
}

func InitAliPan() *AliYunPan {
	return &AliYunPan{
		ClientId:     config.GlobalConfig.AliYunPan.ClientId,
		ClientSecret: config.GlobalConfig.AliYunPan.ClientSecret,
	}
}

func (a *AliYunPan) GenerateTokenByQrCode() {
	qrCode, err := a.GetAuthQRCode()
	if err != nil {
		fmt.Println("获取二维码失败")
		return
	}
	var qrAuthStatus *AuthQrcodeStatusResp
	for {
		qrStatus, err := a.GetAuthStatus(qrCode.Sid)
		if err != nil {
			fmt.Println("获取二维码扫描状态失败")
			return
		}
		if qrStatus.Status == "LoginSuccess" {
			qrAuthStatus = qrStatus
			break
		}
		time.Sleep(time.Second * 5)
	}
	_, err = a.GetAccessToken(qrAuthStatus.AuthCode)
	if err != nil {
		fmt.Println("获取token失败")
	}
	fmt.Println("token已保存到redis")
}

// GetAuthQRCode 获取授权二维码
func (a *AliYunPan) GetAuthQRCode() (*AuthQrCodeResp, error) {
	url := Host + "/oauth/authorize/qrcode"
	body := &AuthQRCode{
		ClientId:            a.ClientId,
		ClientSecret:        a.ClientSecret,
		Scopes:              []string{"user:base", "file:all:read", "file:all:write"},
		CodeChallengeMethod: "plain",
	}
	postBody, err := json.Marshal(body)
	if err != nil {
		return nil, err
	}
	httpServer := utils.InitHttp()
	header := map[string]string{
		"Content-Type": "application/json",
	}
	res, err := httpServer.Do("POST", url, postBody, false, header)
	var result AuthQrCodeResp
	err = json.Unmarshal(res, &result)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

// GetAuthStatus 获取qrcode授权状态
func (a *AliYunPan) GetAuthStatus(sid string) (*AuthQrcodeStatusResp, error) {
	url := Host + "/oauth/qrcode/" + sid + "/status"
	httpServer := utils.InitHttp()
	res, err := httpServer.Do("GET", url, []byte{}, false, make(map[string]string))
	var result AuthQrcodeStatusResp
	err = json.Unmarshal(res, &result)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

// GetAccessToken 获取access_token
func (a *AliYunPan) GetAccessToken(code string) (string, error) {
	redisToken := utils.Get("aliyunpan_accessatoken")
	if redisToken != "" {
		return redisToken, nil
	}
	url := Host + "/oauth/access_token"
	body := &AccessTokenReq{
		ClientId:     config.GlobalConfig.AliYunPan.ClientId,
		ClientSecret: config.GlobalConfig.AliYunPan.ClientSecret,
		GrantType:    "authorization_code",
		Code:         code,
	}
	postBody, err := json.Marshal(body)
	if err != nil {
		return "", err
	}
	httpServer := utils.InitHttp()
	head := map[string]string{
		"Content-Type": "application/json",
	}
	res, err := httpServer.Do("POST", url, postBody, false, head)
	var result AccessTokenResp
	err = json.Unmarshal(res, &result)
	if err != nil {
		return "", err
	}
	utils.Set("aliyunpan_accessatoken", result.AccessToken, time.Second*7000)
	return result.AccessToken, nil
}

// GetUserDriverInfo 获取网盘挂载信息
func (a *AliYunPan) GetUserDriverInfo() (*DriverInfoResp, error) {
	url := Host + "/adrive/v1.0/user/getDriveInfo"
	token, _ := a.GetAccessToken("")
	httpServer := utils.InitHttp()
	httpServer.SetAuth(token)
	res, err := httpServer.Do("POST", url, []byte{}, true, make(map[string]string))
	var result DriverInfoResp
	err = json.Unmarshal(res, &result)
	if err != nil {
		return nil, err
	}
	return &result, nil
}
